import heap.Heap;
import interpreter.Instruction;

import java.util.*;
import java.io.*;

import parser.Parser;

public class Interpreter {
	
	private InputStream programStream;
		
    public static void main(String[] args) {
        // make sure we got one and only one parameter
        if (args.length != 1) {
            System.out.println("Wrong number of arguments - pass program file name");
            System.exit(1);
        }

        // get heap size
        int heapSize = getHeapSize();    

        // initialize Njp VM with program file name, heap size and GC
        Interpreter interpreter = new Interpreter(args[0], heapSize);        
        
        try {
        	
			interpreter.start();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println(e.getMessage());
		}
    	
    }

    /**
     * Initializes Njp interpreter with specified program and heap size.
     * 
     * @param programFile
     *            path to program file
     * @param heapSize
     *            heap size
     */
    public Interpreter(String programFile, int heapSize) {
        // get program code stream
        this.programStream = getProgramStream(programFile);
        Heap.initializeHeap(heapSize);
    }

    /**
     * Opens program file and returns program code input stream.
     * 
     * @param programFile
     *            path to program file
     * @return input stream for program code
     */
    private InputStream getProgramStream(String programFile) {
        InputStream programStream = null;
        try {
            programStream = new FileInputStream(programFile);
        } catch (FileNotFoundException e) {
            System.out.println("Could not open program file: " + programFile + ", exiting.");
            System.exit(2);
        }

        return programStream;
    }

	private static int getHeapSize() {
		return Integer.valueOf(System.getProperty("npj.heap.size"));
	}

	public void start() throws Exception {

		List<Instruction> instructions = new LinkedList<Instruction>();
		BufferedReader br = new BufferedReader(new InputStreamReader(programStream));
		
		String instrLine;		
		while((instrLine = br.readLine())!= null){
			
			if (!instrLine.isEmpty()) {
				if (instrLine.endsWith(";")) {
					instrLine = instrLine.trim(); 
					instrLine = instrLine.substring(0, instrLine.length() - 1);
					instructions.add(Parser.parse(instrLine));
				} else {
					// wyjatek brak srednika
					throw new Exception("Brak srednika");
				}
			}
		}

		//interpretacja
		for (Instruction instruction : instructions) {
			instruction.execute();
		}
	}
	
}
